﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Xml.Linq;
using System.Xml;
using System.Windows.Input;
using System.Windows.Controls;
using System.Windows.Data;
using System.ComponentModel;
using System.Windows.Threading;
using System.Diagnostics;
using System.Collections.ObjectModel;
using System.Net;
using System.IO;
using System.Threading.Tasks;
using for7raid.vkConnector;
using Microsoft.Win32;
using System.Deployment.Application;
using for7raid.Utils;


namespace for7raid.vkPlayer
{
    public class PlayerViewModel : UIElement, INotifyPropertyChanged
    {

        public MediaElement MediaElement { get; set; }

        DispatcherTimer timer = new DispatcherTimer();
        DispatcherTimer ClearStatusTimer = new DispatcherTimer();



        public static bool GetSelected(DependencyObject obj)
        {
            return (bool)obj.GetValue(SelectedProperty);
        }

        public static void SetSelected(DependencyObject obj, bool value)
        {
            obj.SetValue(SelectedProperty, value);
        }

        // Using a DependencyProperty as the backing store for Seceted.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty SelectedProperty =
            DependencyProperty.RegisterAttached("Selected", typeof(bool), typeof(PlayerViewModel), new UIPropertyMetadata(false,
                (d, e) =>
                {

                }
                ));


        public string FilterText
        {
            get { return CurrentPlayList.FilterText; }
            set
            {
                CurrentPlayList.FilterText = value;
                FilterCurrentList();
            }
        }


        public ObservableCollection<PlayList> PlayLists
        {
            get { return (ObservableCollection<PlayList>)GetValue(PlayListsProperty); }
            set { SetValue(PlayListsProperty, value); }
        }

        // Using a DependencyProperty as the backing store for PlayLists.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty PlayListsProperty =
            DependencyProperty.Register("PlayLists", typeof(ObservableCollection<PlayList>), typeof(PlayerViewModel), new UIPropertyMetadata(new ObservableCollection<PlayList>()));


        public PlayList CurrentPlayList
        {
            get { return (PlayList)GetValue(CurrentPlayListProperty); }
            set { SetValue(CurrentPlayListProperty, value); }
        }

        // Using a DependencyProperty as the backing store for CurrentPlayList.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty CurrentPlayListProperty =
            DependencyProperty.Register("CurrentPlayList", typeof(PlayList), typeof(PlayerViewModel), new UIPropertyMetadata(null,
                (d, e) => { (d as PlayerViewModel).OnPropertyChanged("FilterText"); }
                ));

        public ObservableCollection<MediaItem> Items
        {
            get { return CurrentPlayList.Items; }
            set
            {

                CurrentPlayList.Items = value;
                //if (string.IsNullOrEmpty(FilterText))
                //    CurrentPlayList.SearchText = "Свои записи";
                CurrentPlayList.SearchText = string.IsNullOrEmpty(FilterText) ? "Свои записи" : FilterText == "%" ? "Случайные" : FilterText;
                if (Items != null)
                {

                    FilterText = string.Empty;
                    OnPropertyChanged("FilterText");
                    
                }

            }
        }



        public MediaItem CurrentItem
        {
            get { return (MediaItem)GetValue(CurrentItemProperty); }
            set { SetValue(CurrentItemProperty, value); }
        }

        // Using a DependencyProperty as the backing store for CurrentItem.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty CurrentItemProperty =
            DependencyProperty.Register("CurrentItem", typeof(MediaItem), typeof(PlayerViewModel), new UIPropertyMetadata(null,
                (d, e) =>
                {
                    var control = d as PlayerViewModel;
                    var old = e.OldValue as MediaItem;
                    var newitem = e.NewValue as MediaItem;

                    if (old != null) { old.IsCurrent = false; control.MediaElement.Source = null; };
                    if (newitem != null)
                    {
                        newitem.IsCurrent = true;
                        control.MediaElement.Source = new Uri(newitem.URL);
                        //control.MediaElement.Clock = new System.Windows.Media.MediaClock(new System.Windows.Media.MediaTimeline(new Uri(newitem.URL)));
                        control.PlayHistory.Add(newitem);
                        if (control.QueueList.Contains(newitem))
                            control.QueueList.Remove(newitem);

                        if (newitem.lyrics_id > 0 & string.IsNullOrEmpty(newitem.Text))
                            newitem.LoadLirycs();

                    }
                    control.GoToView();

                }));



        public MediaItem SelectedItem
        {
            get { return (MediaItem)GetValue(SelectedItemProperty); }
            set { SetValue(SelectedItemProperty, value); }
        }

        // Using a DependencyProperty as the backing store for SelectedItem.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty SelectedItemProperty =
            DependencyProperty.Register("SelectedItem", typeof(MediaItem), typeof(PlayerViewModel), new UIPropertyMetadata(null));




        public static bool GetIsGrouppedByAlbum(DependencyObject obj)
        {
            return (bool)obj.GetValue(IsGrouppedByAlbumProperty);
        }

        public static void SetIsGrouppedByAlbum(DependencyObject obj, bool value)
        {
            obj.SetValue(IsGrouppedByAlbumProperty, value);
        }

        // Using a DependencyProperty as the backing store for IsGrouppedByAlbum.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty IsGrouppedByAlbumProperty =
            DependencyProperty.RegisterAttached("IsGrouppedByAlbum", typeof(bool), typeof(PlayerViewModel), new UIPropertyMetadata(false,
                (d, e) =>
                {

                    var list = d as PlayList;
                    var view = CollectionViewSource.GetDefaultView(list.Items);
                    if ((bool)e.NewValue)
                    {
                        view.GroupDescriptions.Clear();
                        view.GroupDescriptions.Add(new PropertyGroupDescription("AlbumId"));
                    }
                    else
                    {
                        view.GroupDescriptions.Clear();
                    }

                }
                ));



        public double Position
        {
            get { return MediaElement.Position.TotalMilliseconds; }
            set { MediaElement.Position = TimeSpan.FromMilliseconds(value); }
        }


        public TimeSpan Duration
        {
            get { return (TimeSpan)GetValue(DurationProperty); }
            set { SetValue(DurationProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Duration.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty DurationProperty =
            DependencyProperty.Register("Duration", typeof(TimeSpan), typeof(PlayerViewModel), new UIPropertyMetadata(TimeSpan.FromSeconds(1)));

        public bool IsShuffle
        {
            get { return (bool)GetValue(IsShuffleProperty); }
            set { SetValue(IsShuffleProperty, value); }
        }

        // Using a DependencyProperty as the backing store for IsShuffle.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty IsShuffleProperty =
            DependencyProperty.Register("IsShuffle", typeof(bool), typeof(PlayerViewModel), new UIPropertyMetadata(false));



        public bool IsRepeat
        {
            get { return (bool)GetValue(IsRepeatProperty); }
            set { SetValue(IsRepeatProperty, value); }
        }

        // Using a DependencyProperty as the backing store for IsRepeat.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty IsRepeatProperty =
            DependencyProperty.Register("IsRepeat", typeof(bool), typeof(PlayerViewModel), new UIPropertyMetadata(false));



        public bool IsStopAfterCurrent
        {
            get { return (bool)GetValue(IsStopAfterCurrentProperty); }
            set { SetValue(IsStopAfterCurrentProperty, value); }
        }

        // Using a DependencyProperty as the backing store for IsStopAfterCurrent.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty IsStopAfterCurrentProperty =
            DependencyProperty.Register("IsStopAfterCurrent", typeof(bool), typeof(PlayerViewModel), new UIPropertyMetadata(false));

        public System.Collections.Specialized.StringCollection SearchHistory
        {
            get { return Properties.Settings.Default.SearchHistory; }
        }


        public static bool GetIsStoptAfterThis(DependencyObject obj)
        {
            return (bool)obj.GetValue(IsStopAfterThisProperty);
        }

        public static void SetIsStopAfterThis(DependencyObject obj, bool value)
        {
            obj.SetValue(IsStopAfterThisProperty, value);
        }
        public static readonly DependencyProperty IsStopAfterThisProperty =
            DependencyProperty.RegisterAttached("IsStopAfterThis", typeof(bool), typeof(PlayerViewModel), new UIPropertyMetadata(false));

        

        public ObservableCollection<MediaItem> PlayHistory
        {
            get { return (ObservableCollection<MediaItem>)GetValue(PlayHistoryProperty); }
            set { SetValue(PlayHistoryProperty, value); }
        }

        // Using a DependencyProperty as the backing store for PlayHistory.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty PlayHistoryProperty =
            DependencyProperty.Register("PlayHistory", typeof(ObservableCollection<MediaItem>), typeof(PlayerViewModel), new UIPropertyMetadata(new ObservableCollection<MediaItem>()));




        public List<User> Friends
        {
            get { return (List<User>)GetValue(FriendsProperty); }
            set { SetValue(FriendsProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Friends.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty FriendsProperty =
            DependencyProperty.Register("Friends", typeof(List<User>), typeof(PlayerViewModel), new UIPropertyMetadata(new List<User>()));



        public List<Group> Groups
        {
            get { return (List<Group>)GetValue(GroupsProperty); }
            set { SetValue(GroupsProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Groups.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty GroupsProperty =
            DependencyProperty.Register("Groups", typeof(List<Group>), typeof(PlayerViewModel), new UIPropertyMetadata(new List<Group>()));



        public static ICommand GetUpdateCommand(DependencyObject obj)
        {
            return (ICommand)obj.GetValue(UpdateCommandProperty);
        }

        public static void SetUpdateCommand(DependencyObject obj, ICommand value)
        {
            obj.SetValue(UpdateCommandProperty, value);
        }

        // Using a DependencyProperty as the backing store for UpdateCommand.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty UpdateCommandProperty =
            DependencyProperty.RegisterAttached("UpdateCommand", typeof(ICommand), typeof(PlayerViewModel), new UIPropertyMetadata(null));




        public bool IsShowLyrics
        {
            get { return (bool)GetValue(IsShowLyricsProperty); }
            set { SetValue(IsShowLyricsProperty, value); }
        }

        // Using a DependencyProperty as the backing store for IsShowLyrics.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty IsShowLyricsProperty =
            DependencyProperty.Register("IsShowLyrics", typeof(bool), typeof(PlayerViewModel), new UIPropertyMetadata(true));




        public ObservableCollection<MediaItem> QueueList
        {
            get { return (ObservableCollection<MediaItem>)GetValue(QueueListProperty); }
            set { SetValue(QueueListProperty, value); }
        }

        // Using a DependencyProperty as the backing store for QueueList.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty QueueListProperty =
            DependencyProperty.Register("QueueList", typeof(ObservableCollection<MediaItem>), typeof(PlayerViewModel), new UIPropertyMetadata(new ObservableCollection<MediaItem>()));


        public ObservableCollection<string> StatusText
        {
            get { return (ObservableCollection<string>)GetValue(StatusTextProperty); }
            set { SetValue(StatusTextProperty, value); }
        }

        // Using a DependencyProperty as the backing store for StatusText.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty StatusTextProperty =
            DependencyProperty.Register("StatusText", typeof(ObservableCollection<string>), typeof(PlayerViewModel), new UIPropertyMetadata(new ObservableCollection<string>()));


        public static int GetDownloadProgress(DependencyObject obj)
        {
            return (int)obj.GetValue(DownloadProgressProperty);
        }

        public static void SetDownloadProgress(DependencyObject obj, int value)
        {
            obj.SetValue(DownloadProgressProperty, value);
        }

        // Using a DependencyProperty as the backing store for DownloadProgress.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty DownloadProgressProperty =
            DependencyProperty.RegisterAttached("DownloadProgress", typeof(int), typeof(PlayerViewModel), new UIPropertyMetadata(0));



        public static User GetMediaOwner(DependencyObject obj)
        {
            return (User)obj.GetValue(MediaOwnerProperty);
        }

        public static void SetMediaOwner(DependencyObject obj, User value)
        {
            obj.SetValue(MediaOwnerProperty, value);
        }

        // Using a DependencyProperty as the backing store for MediaOwner.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty MediaOwnerProperty =
            DependencyProperty.RegisterAttached("MediaOwner", typeof(User), typeof(PlayerViewModel), new UIPropertyMetadata(null));



        public int CurrentItemDownloadProgress { get { return (int)(MediaElement.DownloadProgress * 100); } }


        public ICommand SearchCommand { get; set; }
        public ICommand SearchMyCommand { get; set; }
        public ICommand SearchBoxKeyUpCommand { get; set; }
        public ICommand PlaySelectedCommand { get; set; }
        public ICommand QueueCommand { get; set; }
        public ICommand RandomCommand { get; set; }
        public ICommand StopAfterThisCommand { get; set; }

        public static ICommand UpdateFriendCommand { get; set; }
        public static ICommand UpdateGroupCommand { get; set; }


        public static ICommand VolumeMouseCommand { get; set; }

        public static ICommand EditCommand { get; set; }
        public static ICommand AddToMeCommand { get; set; }
        public static ICommand DeleteCommand { get; set; }
        public static ICommand SearchByFriendCommand { get; set; }
        public static ICommand SearchByArtistCommand { get; set; }
        public static ICommand SearchByGroupCommand { get; set; }
        public static ICommand UpdateListCommand { get; set; }
        public static ICommand DownloadCommand { get; set; }
        public static ICommand CopyCommand { get; set; }
        public static ICommand CopyUrlCommand { get; set; }
        public static ICommand ShowUserInfoCommand { get; set; }
        public static ICommand GoToUserCommand { get; set; }

        public static ICommand SendToWallCommand { get; set; }
        public static ICommand SendMesageCommand { get; set; }

        public static ICommand CloseTabCommand { get; set; }
        public static ICommand AddTabCommand { get; set; }

        public static ICommand RemoveFromListCommand { get; set; }

        public ICommand SettingsCommand { get; set; }


        private int _openErrors = 0;

        public PlayerViewModel()
        {


            BindCommands();

            //SetupKeyboardHook();

            MediaElement = new System.Windows.Controls.MediaElement() { LoadedBehavior = MediaState.Manual, UnloadedBehavior = MediaState.Manual };
            MediaElement.MediaOpened += (s, e) => { Duration = MediaElement.NaturalDuration.TimeSpan; _openErrors = 0;  };
            MediaElement.MediaEnded += new RoutedEventHandler(MediaElement_MediaEnded);
            MediaElement.MediaFailed += (s, e) =>
            {

                if (_openErrors > 3)
                {
                    _openErrors = 0;
                    SetStatusText("Возможно список воспроизведения устарел. Нажмите F5 для обновления.");
                }
                else
                {
                    _openErrors++;
                    NextTrack();
                }
            };

            timer.Tick += new EventHandler(timer_Tick);
            timer.Interval = TimeSpan.FromSeconds(0.01D);
            timer.IsEnabled = true;
            timer.Start();


            ClearStatusTimer.Tick += new EventHandler(ClearStatusTimer_Tick);
            ClearStatusTimer.Interval = TimeSpan.FromSeconds(15);
            ClearStatusTimer.IsEnabled = true;

            QueueList.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(QueueList_CollectionChanged);

            SystemEvents.SessionSwitch += new SessionSwitchEventHandler(SystemEvents_SessionSwitch);

            //SearchHistory = new ObservableCollection<string>();

            SetupKeyboardHook();
            SetupProxy();
            Login();

            PlayLists.Add(new PlayList());
            CurrentPlayList = PlayLists.First();

            Properties.Settings.Default.PropertyChanged += new PropertyChangedEventHandler(Default_PropertyChanged);


#if !DEBUG

            UpdateFriendList();
            UpdateGroupList();
#endif

#if DEBUG


            PlayLists.Add(new PlayList() { SearchText = "test1" });
            PlayLists.Add(new PlayList() { SearchText = "test2" });


            Items.Add(new MediaItem() { Artist = "Sia", Title = "soe", URL = "http://cs1249.vkontakte.ru/u3054974/audio/6525e108d164.mp3", Duration = TimeSpan.FromSeconds(600) });
            Items.Add(new MediaItem()
            {
                Artist = "Sia2",
                Title = "soe",
                URL = @"C:\music\Enya\Enya-mp3\Box Of Dreams (Disc 1) - Oceans (320)\Enya - Anywhere Is.mp3",
                Duration = TimeSpan.FromSeconds(423),
                Text = "adlkfjaslj lkfjsd lkafj lkadsjflkasj fkjdsklf jlksadjf lksda jflkjdsl fjal"
            });

            CurrentPlayList = PlayLists[1];

            Items.Add(new MediaItem() { Artist = "Sia_test1", Title = "soe", URL = "http://cs1249.vkontakte.ru/u3054974/audio/6525e108d164.mp3", Duration = TimeSpan.FromSeconds(600) });
            Items.Add(new MediaItem()
            {
                Artist = "Sia2_test1",
                Title = "soe",
                URL = @"C:\music\Enya\Enya-mp3\Box Of Dreams (Disc 1) - Oceans (320)\Enya - Anywhere Is.mp3",
                Duration = TimeSpan.FromSeconds(423),
                Text = "adlkfjaslj lkfjsd lkafj lkadsjflkasj fkjdsklf jlksadjf lksda jflkjdsl fjal",
                Owner = 9046296
            });
#endif
            //Показать окошко что нового, если запускается в первый раз
            if (ApplicationDeployment.IsNetworkDeployed && ApplicationDeployment.CurrentDeployment.IsFirstRun)
            {

                System.Windows.Controls.Primitives.Popup p = Application.Current.FindResource("NewVersionPopup") as System.Windows.Controls.Primitives.Popup;
                p.Placement = System.Windows.Controls.Primitives.PlacementMode.Center;
                p.PlacementTarget = Application.Current.MainWindow;
                p.IsOpen = true;
            }


        }

        //эта процедура следит, если мы меняем настройки в окне настроек - обновляет и тут значения
        void Default_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            switch (e.PropertyName)
            {
                case "IsUseProxy":
                    SetupProxy();
                    break;
                case "IsUseKeyboardHook":
                    SetupKeyboardHook();
                    break;
            }
        }

        /// <summary>
        ///Устанавливает проски для приложения с настройками системы по умолчанию или снимает
        /// </summary>
        private void SetupProxy()
        {
            try
            {
                if (Properties.Settings.Default.IsUseProxy)
                {
                    HttpWebRequest.DefaultWebProxy = WebRequest.GetSystemWebProxy();
                    HttpWebRequest.DefaultWebProxy.Credentials = CredentialCache.DefaultCredentials;
                    WebRequest.DefaultWebProxy = WebRequest.GetSystemWebProxy();
                    WebRequest.DefaultWebProxy.Credentials = CredentialCache.DefaultCredentials;
                }
                else
                {
                    HttpWebRequest.DefaultWebProxy = null;
                    WebRequest.DefaultWebProxy = null;
                }
            }
            catch (Exception e)
            {

            }
        }

        KeyboardHook hook = new KeyboardHook();
        private void SetupKeyboardHook()
        {
            hook.KeyIntercepted += new KeyboardHook.KeyboardHookEventHandler(Keyhook_KeyIntercepted);
            //try
            //{
            //    if (Properties.Settings.Default.IsUseKeyboardHook)
            //    {
            //        hook.KeyIntercepted += new KeyboardHook.KeyboardHookEventHandler(Keyhook_KeyIntercepted);
            //    }
            //    else
            //    {
            //        hook.KeyIntercepted -= Keyhook_KeyIntercepted;
            //    }
            //}
            //catch (Exception)
            //{

            //}
        }

        void Keyhook_KeyIntercepted(KeyboardHook.KeyboardHookEventArgs e)
        {
            //Debug.WriteLine(Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl), "(Keyboard.IsKeyToggled(Key.LeftCtrl) || Keyboard.IsKeyToggled(Key.RightCtrl)");
            //Debug.WriteLine(Keyboard.IsKeyDown(Key.RWin) || Keyboard.IsKeyDown(Key.LWin), "(Keyboard.IsKeyDown(Key.RWin) || Keyboard.IsKeyDown(Key.LWin)");
            ////return;

            //Debug.WriteLine(IsPlaying);
            if (Properties.Settings.Default.IsUseKeyboardHook &
                ((Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl)) &
                (Keyboard.IsKeyDown(Key.RWin) || Keyboard.IsKeyDown(Key.LWin))))

            {
                e.Handled = true; //предположим, что будет команда и нужно прервать обратотку сочетания клавиш
                switch (e.Key)
                {
                        
                    case Key.Left:
                        PreviousTrack();
                        break;
                    case Key.Right:
                        NextTrack();
                        break;
                    case Key.Up:
                        MediaElement.Volume += 0.05;
                        break;
                    case Key.Down:
                        MediaElement.Volume -= 0.05;
                        break;
                    case Key.Space:
                        if (IsPlaying)  Pause(); else Play();
                        break;
                    default:
                        e.Handled = false; //действия не было, передадим на дальнейшую обработку
                        break;
                }
            }

            //обработка специальных клавиш на клавиатуре
            switch (e.Key)
            {

                case Key.MediaPreviousTrack:
                    PreviousTrack();
                    break;
                case Key.MediaNextTrack:
                    NextTrack();
                    break;
                case Key.VolumeUp:
                    MediaElement.Volume += 0.05;
                    break;
                case Key.VolumeDown:
                    MediaElement.Volume -= 0.05;
                    break;
                case Key.MediaPlayPause:
                    Pause();
                    break;
                case Key.MediaStop:
                    if (IsPlaying) Pause(); else Play();
                    break;
                default:
                    break;
            }
        }

        void SystemEvents_SessionSwitch(object sender, SessionSwitchEventArgs e)
        {
            if (e.Reason == SessionSwitchReason.SessionLock)
                MediaElement.Pause();
            else if (e.Reason == SessionSwitchReason.SessionUnlock && MediaElement.Position.TotalSeconds > 0)
                MediaElement.Play();
        }

        private static void Login()
        {
            try
            {
                vkConnector.vkConnector.Login(2036726, 0
                     + 8 //audio
                     + 2 //friends
                     + 8192 //wall
                     + 262144 //groups
                     + 4096 //messages
                     );
            }
            catch (Exception)
            {

                Application.Current.Shutdown();
            }
            try
            {
                vkConnector.User.WhoAmI().ExecAsync(
                        doc =>
                        {


                            User.Me = User.MeFromResponse(doc);

                            Debug.WriteLine("Загружен свой профиль");
                        }
                        );
            }
            catch (Exception ex)
            {

                MessageBox.Show("Не могу получить свой профиль", "вРитме - Ошибка", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

        void QueueList_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            OnPropertyChanged("QueueList");
        }

        void MediaElement_MediaEnded(object sender, RoutedEventArgs e)
        {
            if (GetIsStoptAfterThis(CurrentItem)) //выходим если эта песня помечена как последняя
            {
                SetIsStopAfterThis(CurrentItem, false);
                Stop();
                return;
            }
            else if (IsStopAfterCurrent)
            {
                IsStopAfterCurrent = false;
                Stop();
                return;
            }
            else if (IsRepeat)
            {
                MediaElement.Stop();
                MediaElement.Play();
                return;
            }
            else
                NextTrack();
        }

        public bool IsPlaying
        {
            get
            {
                if (MediaElement.Position.TotalSeconds == 0)
                    return false;
                else
                    return true;
            }
        }

        private void BindCommands()
        {
            CommandBinding cb = new CommandBinding(MediaCommands.PreviousTrack);
            cb.Executed += (s, e) => { PreviousTrack(); };
            this.CommandBindings.Add(cb);

            cb = new CommandBinding(MediaCommands.NextTrack);
            cb.Executed += (s, e) => { NextTrack(); };
            this.CommandBindings.Add(cb);

            cb = new CommandBinding(MediaCommands.Stop);
            cb.Executed += new ExecutedRoutedEventHandler(StopCommand_Executed);
            this.CommandBindings.Add(cb);

            cb = new CommandBinding(MediaCommands.Play);
            cb.Executed += (s, e) => { Play(); };
            this.CommandBindings.Add(cb);

            cb = new CommandBinding(MediaCommands.Pause);
            cb.Executed += (s, e) => { Pause(); };
            this.CommandBindings.Add(cb);

            VolumeMouseCommand = new for7raid.Control.SimpleCommand(p => VolumeMouse(p as MouseWheelEventArgs));

            EditCommand = new for7raid.Control.SimpleCommand(p => Edit(p), p => CanBeEdited(p as MediaItem));

            SearchCommand = new for7raid.Control.SimpleCommand(p => { if (p == null || (p as KeyEventArgs).Key == Key.Enter) Search(); });
            SearchMyCommand = new for7raid.Control.SimpleCommand(p => { FilterText = ""; Search(); });
            SearchBoxKeyUpCommand = new for7raid.Control.SimpleCommand(p => { if ((p as KeyEventArgs).Key == Key.Enter) Search(); });
            PlaySelectedCommand = new for7raid.Control.SimpleCommand(p => PlaySelectedExecuted(p));
            SearchByFriendCommand = new for7raid.Control.SimpleCommand(p => { SearchByFriend(p as User); });
            SearchByGroupCommand = new for7raid.Control.SimpleCommand(p => { SearchByGroup(p as Group); });
            SearchByArtistCommand = new for7raid.Control.SimpleCommand(p => { SearchByArtist(p as MediaItem); });
            RandomCommand = new for7raid.Control.SimpleCommand(p => { FilterText = "%"; Search(); });
            UpdateListCommand = new for7raid.Control.SimpleCommand(p => { UpdateList(); });

            AddToMeCommand = new for7raid.Control.SimpleCommand(p => { AddToMe(p as MediaItem); }, p => CanBeAddedToMe(p as MediaItem));
            DeleteCommand = new for7raid.Control.SimpleCommand(p => { DeleteMyAudio(p as MediaItem); }, p => CanBeDeleted(p as MediaItem));
            DownloadCommand = new for7raid.Control.SimpleCommand(p => { DownloadAudio(p as MediaItem); });
            CopyCommand = new for7raid.Control.SimpleCommand(p => { Copy(p as MediaItem); });
            CopyUrlCommand = new for7raid.Control.SimpleCommand(p => { CopyUrl(p as MediaItem); });
            ShowUserInfoCommand = new for7raid.Control.SimpleCommand(p => { ShowUserInfo(p as MediaItem); }, p => { return p != null && (p as MediaItem).Owner > 0; });
            GoToUserCommand = new for7raid.Control.SimpleCommand(p => { GoToUser(p as User); });

            UpdateFriendCommand = new for7raid.Control.SimpleCommand(p => { UpdateFriendList(); });
            UpdateGroupCommand = new for7raid.Control.SimpleCommand(p => { UpdateGroupList(); });

            QueueCommand = new for7raid.Control.SimpleCommand(p => { InQueue(); });
            StopAfterThisCommand = new for7raid.Control.SimpleCommand(p => { StopAfterThis(p as MediaItem); });
            RemoveFromListCommand = new for7raid.Control.SimpleCommand(p => { RemoveFromList(p as MediaItem); });

            SendToWallCommand = new for7raid.Control.SimpleCommand(p => { SendToWall(p as User); });
            SendMesageCommand = new for7raid.Control.SimpleCommand(p => { SendMessage(p as User); });

            CloseTabCommand = new for7raid.Control.SimpleCommand(p => { CloseTab(p as PlayList); }, p => CanCloseTab(p as PlayList));
            AddTabCommand = new for7raid.Control.SimpleCommand(p => AddTab());

            SettingsCommand = new for7raid.Control.SimpleCommand(p => ShowSettings());

        }

        private void StopAfterThis(MediaItem mediaItem)
        {
            SetIsStopAfterThis(mediaItem, !GetIsStoptAfterThis(mediaItem));
        }

        private void ShowSettings()
        {
            var window = new SettingsWindow();
            window.DataContext = new SettingsViewModel();
            window.Owner = Application.Current.MainWindow;
            window.ShowDialog();
        }



        private void VolumeMouse(MouseWheelEventArgs mouseWheelEventArgs)
        {
            if (mouseWheelEventArgs.Delta > 0)
                MediaElement.Volume += 0.05;
            else
                MediaElement.Volume -= 0.05;
        }

        private void UpdateList()
        {
            try
            {
                var ids = Items.Select(i => i.Owner.ToString() + "_" + i.ID).ToArray();


                Request req = Audio.GetByIds(ids);


                req.ExecAsync(doc =>
                {
                    var tmpItems = MediaItem.FromResponse(doc);

                    foreach (var item in tmpItems)
                    {
                        var oldItem = Items.FirstOrDefault(i => i.ID == item.ID);
                        if (oldItem != null)
                            oldItem.URL = item.URL;
                    }

                    SetStatusText("Список обновлен");

                });

            }
            catch (Exception ex)
            {

                MessageBox.Show("Не могу обновить список воспроизведения", "вРитме - Ошибка", MessageBoxButton.OK, MessageBoxImage.Error);
                ClearMediaItems();
            }
        }

        private void GoToUser(User user)
        {
            var url = @"http://vk.com/id" + user.uid.ToString();
            Process.Start(url);
        }

        private void ShowUserInfo(MediaItem mediaItem)
        {
            vkConnector.User.GetProfile(mediaItem.Owner)
            .ExecAsync(doc =>
            {
                var user = User.FromResponse(doc).First();
                SetMediaOwner(mediaItem, user);
                Debug.WriteLine("Пользователь загружен");
            }
            );
        }

        private void RemoveFromList(MediaItem item)
        {
            Items.Remove(item);
        }

        private void AddTab()
        {
            PlayLists.Add(new PlayList());
            CurrentPlayList = PlayLists.Last();
        }

        private bool CanCloseTab(PlayList playList)
        {
            return PlayLists.Count > 1;
        }

        private void CloseTab(PlayList playList)
        {
            int index = PlayLists.IndexOf(playList);
            index = (index == 0) ? 1 : index - 1; //сделаем активной рядомстоящую вкладку: если закрываем первую - тогда справа, иначе слева
            CurrentPlayList = PlayLists[index];
            PlayLists.Remove(playList);

        }

        private void SendToWall(User p)
        {
            try
            {
                p = p ?? User.Me;// если ничего не передалось - значит нужно себе на стену запостить
                var files = Items.Where(i => GetSelected(i)).ToList();
                string attachments = (files.Count > 1) ? //у нас выбран один файл или много?
                    files.Select(i => "audio" + i.Owner + "_" + i.ID).Aggregate((i, l) => i + "," + l) : //все выделенные файлы
                    "audio" + SelectedItem.Owner + "_" + SelectedItem.ID; //или только по тому, где кликнули
                var box = new InputBox();
                if (box.ShowDialog() == true)
                    Wall.Post(p.uid, attachments, box.Message.Text)
                        .ExecAsync(doc => { SetStatusText("Запись отправлена на стену"); });
            }
            catch (Exception ex)
            {

                MessageBox.Show("Не могу отправить запись на стену!", "вРитме - Ошибка", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

        private void SendMessage(User p)
        {
            try
            {
                p = p ?? User.Me;// если ничего не передалось - значит нужно себе на стену запостить
                //p = User.Me;
                var files = Items.Where(i => GetSelected(i)).ToList();
                string attachments = (files.Count > 1) ? //у нас выбран один файл или много?
                    files.Select(i => "audio" + i.Owner + "_" + i.ID).Aggregate((i, l) => i + "," + l) : //все выделенные файлы
                    "audio" + SelectedItem.Owner + "_" + SelectedItem.ID; //или только по тому, где кликнули
                var box = new InputBox();
                if (box.ShowDialog() == true)
                    Messages.Send(p.uid, "Музыкальная посылка вРитме", box.Message.Text, attachments)
                        .ExecAsync(doc => { SetStatusText("Сообщение отправлено"); });
            }
            catch (Exception ex)
            {

                MessageBox.Show("Не могу отправить сообщение!", "вРитме - Ошибка", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

        private void Copy(MediaItem mediaItem)
        {


            DataObject data = new DataObject();

            //data.SetData(mediaItem);

            data.SetText(mediaItem.Artist + " - " + mediaItem.Title);

            data.SetData(new Uri(mediaItem.URL, UriKind.RelativeOrAbsolute));

            Clipboard.SetDataObject(data);

        }

        private void CopyUrl(MediaItem mediaItem)
        {


            DataObject data = new DataObject();

            //data.SetData(mediaItem);

            data.SetText(mediaItem.URL);


            Clipboard.SetDataObject(data);

        }

        private void InQueue()
        {
            if (QueueList.Contains(SelectedItem))
                QueueList.Remove(SelectedItem);
            else
                QueueList.Add(SelectedItem);

            OnPropertyChanged("QueueList");
        }

        void StopCommand_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            if (Keyboard.Modifiers.HasFlag(ModifierKeys.Control))
                IsStopAfterCurrent = !IsStopAfterCurrent;
            else
                Stop();
        }

        private void PlaySelectedExecuted(object p)
        {
            if (p == null || (p is KeyEventArgs && (p as KeyEventArgs).Key == Key.Enter) ||
                (p is MouseButtonEventArgs && ((p as MouseButtonEventArgs).OriginalSource is TextBlock)))
                PlaySelected();
        }

        private bool CanBeEdited(MediaItem mediaItem)
        {
            return Items != null && Items.Count(i => GetSelected(i)) == 1;
        }

        private void SearchByArtist(MediaItem mediaItem)
        {
            FilterText = mediaItem.Artist;
            Search();
        }

        private void SetStatusText(string text)
        {
            StatusText.Add(text);
            if (StatusText.Count > 3)
                StatusText.RemoveAt(0);

            ClearStatusTimer.Stop();
            ClearStatusTimer.Start();
        }

        void ClearStatusTimer_Tick(object sender, EventArgs e)
        {
            StatusText.Clear();
            ClearStatusTimer.Stop();
        }

        string _downdloadPath;
        private void DownloadAudio(MediaItem mediaItem)
        {
            var files = Items.Where(i => GetSelected(i)).ToList();
            if (files.Count == 1)
            {
                Microsoft.Win32.SaveFileDialog dlg = new Microsoft.Win32.SaveFileDialog();
                dlg.FileName = mediaItem.Artist + " - " + mediaItem.Title; // Default file name
                dlg.DefaultExt = ".mp3"; // Default file extension
                dlg.Filter = "MP3 files (.mp3)|*.mp3"; // Filter files by extension

                // Show save file dialog box
                Nullable<bool> result = dlg.ShowDialog();

                // Process save file dialog box results
                if (result == true)
                {
                    // Save document
                    string filename = dlg.FileName;
                    WebClient Client = new WebClient();
                    Client.DownloadFileCompleted += (s, e) =>
                    {
                        var item = (e.UserState as MediaItem);
                        SetStatusText("Загружен файл " + item.Artist + " - " + item.Title);
                    };
                    Client.DownloadProgressChanged += (s, e) =>
                        {
                            var item = (e.UserState as MediaItem);
                            SetDownloadProgress(item, e.ProgressPercentage);
                        };
                    Client.DownloadFileAsync(new Uri(mediaItem.URL, UriKind.Absolute), filename, mediaItem);


                }
            }
            else if (files.Count > 1)
            {
                // Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();
                var dlg = new System.Windows.Forms.FolderBrowserDialog();
                dlg.SelectedPath = _downdloadPath;
                if (dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                {
                    _downdloadPath = dlg.SelectedPath;

                    Action<object> downloadAction = (object m) =>
                    {
                        var item = m as MediaItem;
                        var filename = Path.Combine(dlg.SelectedPath, item.Artist + " - " + item.Title + ".mp3");
                        WebClient Client = new WebClient();
                        try
                        {
                            //Client.DownloadFile(new Uri(item.URL, UriKind.Absolute), filename);
                            Client.DownloadProgressChanged += (s, e) =>
                            {
                                Dispatcher.BeginInvoke(
                                (Action<int>)delegate(int progress) { SetDownloadProgress(item, progress); },
                                 e.ProgressPercentage);

                            };
                            Client.DownloadFileAsync(new Uri(item.URL, UriKind.Absolute), filename, item);
                            while (Client.IsBusy)
                            {
                                System.Threading.Thread.Sleep(1000);
                            }

                        }
                        catch
                        {
                            Dispatcher.BeginInvoke(
                                (Action<string>)delegate(string name) { SetStatusText("Ошибка загрузки " + name); },
                                Path.GetFileNameWithoutExtension(filename));

                        }

                    };

                    Action<Task[]> endDownloadedAction = (Task[] ts) =>
                    {
                        Dispatcher.BeginInvoke((Action)delegate() { SetStatusText("Все файлы загружены"); });
                    };

                    Task[] tasks = new Task[files.Count];
                    for (int i = 0; i < files.Count; i++)
                    {
                        tasks[i] = Task.Factory.StartNew(downloadAction, files[i]);
                    }

                    Task.Factory.ContinueWhenAll(tasks, endDownloadedAction);
                }


            }

        }



        private bool CanBeDeleted(MediaItem mediaItem)
        {
            return mediaItem != null &&
                User.Me != null &&
                mediaItem.Owner == User.Me.uid &&
                Items != null &&
                Items.Count(i => GetSelected(i)) == 1;
        }

        private void DeleteMyAudio(MediaItem mediaItem)
        {
            if (MessageBox.Show
                (string.Format("Вы действительно хотите удалить запись {0} - {1}", mediaItem.Artist, mediaItem.Title),
                "Удаление своей записи", MessageBoxButton.YesNo, MessageBoxImage.Question, MessageBoxResult.No
                ) == MessageBoxResult.Yes &&
                    mediaItem.Delete())
            {
                Items.Remove(mediaItem);
                SetStatusText("Запись удалена");
            }
        }

        private void AddToMe(MediaItem mediaItem)
        {
            try
            {
                Audio.AddAudio(mediaItem.ID, mediaItem.Owner).ExecAsync(doc =>
                    {
                        SetStatusText("Запись добавлена");
                        mediaItem.Owner = User.MeId;
                    });
            }
            catch (Exception)
            {

                MessageBox.Show("Не могу добавить запись!", "Ошибка", MessageBoxButton.OK, MessageBoxImage.Error);
            }

        }

        private bool CanBeAddedToMe(MediaItem mediaItem)
        {
            return mediaItem != null &&
                User.Me != null &&
                mediaItem.Owner != User.Me.uid &&
                Items != null &&
                Items.Count(i => GetSelected(i)) == 1;
        }

        private void SearchByGroup(Group group)
        {

            if (Keyboard.Modifiers.HasFlag(ModifierKeys.Control))
                AddTab();

            FilterText = group.Name;
            Items = null;
            try
            {
                Audio.GetByGroupId(group.ID).ExecAsync(
                    doc =>
                    {
                        Items = MediaItem.FromResponse(doc);
                    });

                //Audio.GetAlbumsByGroupId(group.ID).ExecAsync(doc =>
                //    {
                //        CurrentPlayList.Albums = Album.FromResponse(doc);
                //    });
            }
            catch (Exception ex)
            {

                MessageBox.Show("Не могу получить список воспроизведения группы", "вРитме - Ошибка", MessageBoxButton.OK, MessageBoxImage.Error);
                ClearMediaItems();
            }
        }

        private void SearchByFriend(User user)
        {

            if (Keyboard.Modifiers.HasFlag(ModifierKeys.Control))
                AddTab();

            FilterText = user.FirstName + " " + user.LastName;
            Items = null;
            try
            {
                Audio.GetByUserId(user.uid).ExecAsync(doc =>
                    {
                        Items = MediaItem.FromResponse(doc);
                    });

                //Audio.GetAlbumsByUserId(user.uid).ExecAsync(doc =>
                //{
                //    CurrentPlayList.Albums = Album.FromResponse(doc);
                //});

            }
            catch (Exception ex)
            {

                MessageBox.Show("Не могу получить список воспроизведения друга", "вРитме - Ошибка", MessageBoxButton.OK, MessageBoxImage.Error);
                ClearMediaItems();
            }


        }

        private void Edit(object e)
        {
            var item = e as MediaItem;
            new EditViewModel(item).BindToView(new EditItem()).ShowDialog();
        }

        private void GoToView()
        {
            //var view = CollectionViewSource.GetDefaultView(Items);
            //view.MoveCurrentTo(CurrentItem);
            //view.Refresh();
            SelectedItem = CurrentItem;

        }

        private void NextTrack()
        {
            if (Items == null && Items.Count == 0) //выходим если лист пуст
            {
                Stop();
                return;
            }

            int index = 0;

            if (QueueList.Count > 0)
            {
                var item = QueueList.First();
                if (CurrentItem == item)
                {
                    QueueList.Remove(item);
                    MediaElement.Stop();
                    MediaElement.Play();
                }
                else
                {
                    CurrentItem = item;
                }
                return;
            }
            else if (!IsShuffle)
            {
                index = Items.IndexOf(CurrentItem);
                if (index < Items.Count - 1)
                    index++;
                else
                    index = 0;
            }
            else
            {
                var rand = new Random();
                index = rand.Next(Items.Count - 1);
            }

            if (Items != null && Items.Count > 0)
                CurrentItem = Items[index];
        }

        private void PreviousTrack()
        {
            if (!IsShuffle)
            {
                int index = Items.IndexOf(CurrentItem);
                if (index > 0)
                    index--;
                else
                    index = Items.Count - 1;
                CurrentItem = Items[index];
            }
            else
            {
                if (PlayHistory.Count > 1 && PlayHistory.IndexOf(CurrentItem) >= 0)
                    CurrentItem = PlayHistory[PlayHistory.IndexOf(CurrentItem) - 1];
                else CurrentItem = PlayHistory.LastOrDefault();
            }
        }




        private void Play()
        {
            //if (MediaElement.CanPause) MediaElement.Stop();
            if (CurrentItem != SelectedItem && SelectedItem != null) CurrentItem = SelectedItem;
            if (CurrentItem == null && Items != null && Items.Count > 0) CurrentItem = Items.First();
            MediaElement.Play();
        }

        private void Pause()
        {
            MediaElement.Pause();
            
        }

        private void Stop()
        {
            IsStopAfterCurrent = false;
            MediaElement.Stop();
        }

        void timer_Tick(object sender, EventArgs e)
        {
            ShowProgress();

        }

        private void ShowProgress()
        {
            OnPropertyChanged("Position");
            OnPropertyChanged("CurrentItemDownloadProgress");
        }

        private void Search()
        {
            if (Keyboard.Modifiers.HasFlag(ModifierKeys.Control))
            {
                string sText = FilterText;
                FilterText = string.Empty;
                AddTab();
                FilterText = sText;
            }

            try
            {

                Items = null;


                Request req = FilterText == "%" ? Audio.GetRandom() :
                    string.IsNullOrEmpty(FilterText) ?
                    Audio.GetMyAudio() : //свои записи
                            Audio.Search(FilterText.Replace("*", ""), FilterText.Contains('*')); //поиск с текстом если была звездочкка в запросе

                FilterText = FilterText.Replace("*", "");

                req.ExecAsync(doc =>
                    {
                        Items = MediaItem.FromResponse(doc,true);
                        if (!string.IsNullOrEmpty(FilterText) && !SearchHistory.Contains(FilterText))
                        {
                            SearchHistory.Insert(0, FilterText);
                            if (SearchHistory.Count > 20)
                                SearchHistory.RemoveAt(SearchHistory.Count - 1);
                        }
                    });

                //if (string.IsNullOrEmpty(FilterText) && User.Me != null) //Загрузим свои альбомы
                //{
                //    Audio.GetAlbumsByUserId(User.Me.uid).ExecAsync(doc =>
                //    {
                //        CurrentPlayList.Albums = Album.FromResponse(doc);
                //    });
                //}

            }
            catch (Exception ex)
            {

                MessageBox.Show("Не могу получить список воспроизведения", "вРитме - Ошибка", MessageBoxButton.OK, MessageBoxImage.Error);
                ClearMediaItems();
            }
        }

        private void UpdateFriendList()
        {
            try
            {

                Friends = null;

                vkConnector.User.GetMyFriends().ExecAsync(doc =>
                    {

                        Friends = User.FromResponse(doc);
                    });

            }
            catch (Exception ex)
            {

                MessageBox.Show("Не могу получить список друзей", "вРитме - Ошибка", MessageBoxButton.OK, MessageBoxImage.Error);
                ClearValue(FriendsProperty);
            }
        }

        private void UpdateGroupList()
        {
            try
            {

                Groups = null;

                vkConnector.User.GetMyGroups().ExecAsync(doc =>
                    {
                        Groups = Group.FromResponse(doc);
                    });

            }
            catch (Exception ex)
            {

                MessageBox.Show("Не могу получить список групп", "вРитме - Ошибка", MessageBoxButton.OK, MessageBoxImage.Error);
                ClearValue(GroupsProperty);
            }
        }


        private void PlaySelected()
        {
            MediaElement.Stop();
            CurrentItem = SelectedItem;
            MediaElement.Play();

        }

        public void FilterCurrentList()
        {
            var view = CollectionViewSource.GetDefaultView(Items);
            var text = (FilterText ?? "").ToLower();
            if (view != null)
                view.Filter = (e) => { return ((e as MediaItem).Artist + (e as MediaItem).Title).ToLower().Contains(text.ToLower()); };

        }

        #region Члены INotifyPropertyChanged

        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged(string Name)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(Name));
        }

        #endregion

        public void ClearMediaItems()
        {
            if (Items == null)
                Items = new ObservableCollection<MediaItem>();
            else
                Items.Clear();
        }
    }
}
